// 这个是路由转发功能  --- 转发消息
#pragma once
#include "Common.hpp"
#include "InteInfo.hpp"
#include "Log.hpp"
#include "Mutex.hpp"
#include <vector>

using namespace LogModel;
using namespace MutexModel;

// 消息是发给各个在线用户的 , 用户是谁啊 ?? 不就是一个个的 ip和端口号吗
// 所以 , 不就是一个个 InteInfo 类吗 , 所以将其管理起来
class Route
{
private:
    // 1. 判断用户是否在线 , 怎么判断啊 ,不就是判断 InteInfo 信息是否存在吗
    bool IsExist(InteInfo &peer)
    {
        // 遍历 _online_user
        for (auto &user : _online_user)
        {
            if (user == peer)
            {
                return true; // 存在
            }
        }
        return false;
    }

    // 2. 添加用户
    void AddUser(InteInfo &user)
    {
        // 多线程要加锁 , 防止数据不一致
        LockGuard lockguard(_mutex);
        LOG(LogLevel::INFO) << "新增了一个用户 : [ " << user.GetIp() << " " << user.GetPort() << " ]";
        _online_user.emplace_back(user);
    }

    // 3. 删除用户
    void DeleteUser(InteInfo &user)
    {
        //erase -- 用的是 vector , 这个是迭代器
        for(auto iter = _online_user.begin(); iter != _online_user.end(); ++iter)
        {
            //iter 是迭代器 - 是指针 , 指向每个InteInfo类型
           if(*iter == user)
           {
                //删除
                _online_user.erase(iter);
                break; // 删除完跳出 ,防止迭代器失效 
           }
        }
    }

public:
    Route() {}

    // 消息转发 -- 转发给在线用户
    // 转发是依靠网络的 , 所以要有文件描述符
    void MessageRoute(int sockfd, const std::string &message, InteInfo &who)
    {
        // 1. 判断用户是否在线 , 不存在添加用户
        if (!IsExist(who))
        {
            // 添加该用户
            AddUser(who);
        }

        // 自定义信息
        std::string route_message = who.InfoAddr() + message;

        // 2. 转发 -- 发 -- sendto (Udp) , 要给所有在线用户都发该消息
        for (auto &online : _online_user)
        {
            sendto(sockfd, route_message.c_str(), route_message.size(), 0,
                   who.InteAddrToSockAddr(), who.SockAddrLen());
        }

        // 3. 如果用户已经在线 , 想要退出
        if (message == "QUIT")
        {
            LockGuard lockguard(_mutex);

            LOG(LogLevel::INFO) << "删除一个在线用户: " << who.InfoAddr();
            DeleteUser(who);
        }
    }

private:
    std::vector<InteInfo> _online_user; // 在线用户
    Mutex _mutex;
};